Skip to content

fix: normalize fileName property to handle case-insensitivity#2471

Open
enzowilliam wants to merge 2 commits intoEvolutionAPI:mainfrom
enzowilliam:fix/filename-property-inconsistency
Open

fix: normalize fileName property to handle case-insensitivity#2471
enzowilliam wants to merge 2 commits intoEvolutionAPI:mainfrom
enzowilliam:fix/filename-property-inconsistency

Conversation

@enzowilliam
Copy link

@enzowilliam enzowilliam commented Mar 11, 2026

Summary

  • Fixes the inconsistency in the /message/sendMedia/{instance} endpoint where the fileName property was case-sensitive
  • For images, only filename (lowercase) worked
  • For documents/videos, only fileName (camelCase) worked
  • Now both fileName and filename are accepted for all media types

Changes

Added property normalization at the beginning of the mediaMessage method in all three channel services:

  • src/api/integrations/channel/whatsapp/whatsapp.baileys.service.ts
  • src/api/integrations/channel/evolution/evolution.channel.service.ts
  • src/api/integrations/channel/meta/whatsapp.business.service.ts

The fix normalizes filename to fileName by using:

fileName: data.fileName || (data as any).filename,

Test plan

  • Send image with fileName property - should work
  • Send image with filename property - should work
  • Send document with fileName property - should work
  • Send document with filename property - should work
  • Send video with fileName property - should work
  • Send video with filename property - should work

Closes #2459

🤖 Generated with Claude Code

Summary by Sourcery

Normalize media message filename handling across channels and refine group mention options for message schemas and WhatsApp integration.

Bug Fixes:

  • Allow both fileName and filename properties when sending media messages across WhatsApp, Evolution, and Meta channel services.
  • Ensure mentionsEveryOne only applies when explicitly set to true in WhatsApp Baileys group messaging.

Enhancements:

  • Rename message schema property from everyOne to mentionsEveryOne for clearer and more consistent API semantics across all message types.

enzowilliam and others added 2 commits March 11, 2026 15:48
- Changed truthy check to strict equality (=== true) to properly handle
  string values like "false" sent by clients (e.g., n8n)
- Fixed validation schema property name from 'everyOne' to 'mentionsEveryOne'
  to match DTO and service code

Fixes EvolutionAPI#2431

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The sendMedia endpoint had an inconsistency where:
- For images: only `filename` (lowercase) worked
- For documents/videos: only `fileName` (camelCase) worked

This was caused by the code only checking `data.fileName` without
considering that users might send `filename` (lowercase) in the
JSON payload.

This fix normalizes the property name at the beginning of the
mediaMessage method in all three channel services:
- whatsapp.baileys.service.ts
- evolution.channel.service.ts
- whatsapp.business.service.ts

Now both `fileName` and `filename` are accepted for all media types.

Closes EvolutionAPI#2459

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@sourcery-ai
Copy link
Contributor

sourcery-ai bot commented Mar 11, 2026

Reviewer's Guide

Normalizes the SendMedia DTO so both fileName and filename are accepted across all WhatsApp channel integrations, and renames the everyOne mention flag to mentionsEveryOne consistently in message validation schemas and Baileys service logic.

Sequence diagram for sendMedia filename normalization

sequenceDiagram
  actor Client
  participant Api as MessageApi
  participant Chan as ChannelService
  participant WA as WhatsappProvider

  Client->>Api: POST /message/sendMedia/{instance}\nbody { fileName or filename }
  Api->>Chan: mediaMessage(data, file, isIntegration)

  alt data.fileName is defined
    Chan->>Chan: Build mediaData with fileName = data.fileName
  else data.fileName is undefined and data.filename is defined
    Chan->>Chan: Build mediaData with fileName = data.filename
  end

  Chan->>Chan: if file provided\nset mediaData.media = file buffer base64
  Chan->>WA: Send normalized mediaData
  WA-->>Chan: Provider response
  Chan-->>Api: Normalized send result
  Api-->>Client: HTTP response
Loading

Class diagram for updated message mention schemas

classDiagram
  class TextMessageSchema {
    +boolean mentionsEveryOne
    +array mentioned
  }
  class MediaMessageSchema {
    +boolean mentionsEveryOne
    +array mentioned
  }
  class PtvMessageSchema {
    +boolean mentionsEveryOne
    +array mentioned
  }
  class AudioMessageSchema {
    +boolean mentionsEveryOne
    +array mentioned
  }
  class StickerMessageSchema {
    +boolean mentionsEveryOne
    +array mentioned
  }
  class LocationMessageSchema {
    +boolean mentionsEveryOne
    +array mentioned
  }
  class PollMessageSchema {
    +boolean mentionsEveryOne
    +array mentioned
  }
  class ListMessageSchema {
    +boolean mentionsEveryOne
    +array mentioned
  }
  class ButtonsMessageSchema {
    +boolean mentionsEveryOne
    +array mentioned
  }

  TextMessageSchema <|-- MediaMessageSchema
  TextMessageSchema <|-- PtvMessageSchema
  TextMessageSchema <|-- AudioMessageSchema
  TextMessageSchema <|-- StickerMessageSchema
  TextMessageSchema <|-- LocationMessageSchema
  TextMessageSchema <|-- PollMessageSchema
  TextMessageSchema <|-- ListMessageSchema
  TextMessageSchema <|-- ButtonsMessageSchema
Loading

Flow diagram for mentionsEveryOne handling in Baileys service

flowchart TD
  A[Start building mentions list] --> B{options.mentionsEveryOne === true}
  B -->|yes| C[Set mentions to all group participants ids]
  B -->|no| D{options.mentioned has items}
  D -->|yes| E[Map each mentioned value to participant id]
  D -->|no| F[Leave mentions empty]
  C --> G[Continue sending message]
  E --> G[Continue sending message]
  F --> G[Continue sending message]
Loading

File-Level Changes

Change Details Files
Normalize media filename input to support both fileName and filename for all media types in all WhatsApp channel services.
  • Change mediaMessage construction to spread incoming data while overriding/setting fileName
  • Derive fileName from either existing data.fileName or legacy lowercase data.filename
  • Ensure file attachment buffer is still converted to base64 and assigned to media
src/api/integrations/channel/whatsapp/whatsapp.baileys.service.ts
src/api/integrations/channel/evolution/evolution.channel.service.ts
src/api/integrations/channel/meta/whatsapp.business.service.ts
Rename the broadcast-mention boolean flag from everyOne to mentionsEveryOne across message validation schemas and tighten its usage in Baileys service.
  • Update JSON schemas for all message types to use mentionsEveryOne instead of everyOne
  • Keep mentionsEveryOne typed as a boolean enum [true, false] in schemas
  • Require options.mentionsEveryOne to be strictly true before auto-mentioning all group participants
src/validate/message.schema.ts
src/api/integrations/channel/whatsapp/whatsapp.baileys.service.ts

Assessment against linked issues

Issue Objective Addressed Explanation
#2459 Fix the /message/sendMedia/{instance} endpoint so that the file name field behaves consistently across all media types (image, video, document), eliminating the bug where images only worked with filename and documents/videos only with fileName.
#2459 Standardize on a single canonical property name (fileName) in the public API contract and documentation, fully aligning the documented payload with the actual implementation. The PR changes only backend service code to normalize filename to fileName in mediaMessage methods; it does not modify any API documentation or schemas related to the documented contract, so alignment of docs/contract with the new behavior is not covered here.

Possibly linked issues


Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

Copy link
Contributor

@sourcery-ai sourcery-ai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey - I've found 1 issue, and left some high level feedback:

  • Renaming everyOne to mentionsEveryOne across all message schemas may be a breaking API change for existing clients; consider either keeping everyOne as a deprecated alias in the schema or handling both properties during validation/normalization similar to the fileName/filename approach.
  • The mediaMessage normalization logic for fileName is duplicated in three services; consider extracting a shared helper or applying normalization at a DTO/validation layer to avoid drift between channel implementations.
  • Using fileName: data.fileName || (data as any).filename will overwrite an explicitly provided empty string fileName with filename; if that matters for your API, consider using nullish coalescing (??) instead of ||.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- Renaming `everyOne` to `mentionsEveryOne` across all message schemas may be a breaking API change for existing clients; consider either keeping `everyOne` as a deprecated alias in the schema or handling both properties during validation/normalization similar to the `fileName`/`filename` approach.
- The `mediaMessage` normalization logic for `fileName` is duplicated in three services; consider extracting a shared helper or applying normalization at a DTO/validation layer to avoid drift between channel implementations.
- Using `fileName: data.fileName || (data as any).filename` will overwrite an explicitly provided empty string `fileName` with `filename`; if that matters for your API, consider using nullish coalescing (`??`) instead of `||`.

## Individual Comments

### Comment 1
<location path="src/api/integrations/channel/whatsapp/whatsapp.baileys.service.ts" line_range="2981-2986" />
<code_context>
+    const mediaData: SendMediaDto = {
+      ...data,
+      // Normalize filename to fileName (handle case-insensitivity)
+      fileName: data.fileName || (data as any).filename,
+    };

</code_context>
<issue_to_address>
**suggestion:** Overriding `fileName` after spreading may mask an existing, intentionally empty `fileName` value.

If `data.fileName` is an empty string (or another falsy-but-valid value), this will incorrectly fall back to `(data as any).filename`. Prefer checking only for `undefined`, e.g. `fileName: data.fileName ?? (data as any).filename`, so intentional empty values are preserved.

```suggestion
  public async mediaMessage(data: SendMediaDto, file?: any, isIntegration = false) {
    const mediaData: SendMediaDto = {
      ...data,
      // Normalize filename to fileName (handle case-insensitivity) while preserving intentional empty values
      fileName: data.fileName ?? (data as any).filename,
    };
```
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

Comment on lines 2981 to +2986
public async mediaMessage(data: SendMediaDto, file?: any, isIntegration = false) {
const mediaData: SendMediaDto = { ...data };
const mediaData: SendMediaDto = {
...data,
// Normalize filename to fileName (handle case-insensitivity)
fileName: data.fileName || (data as any).filename,
};
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suggestion: Overriding fileName after spreading may mask an existing, intentionally empty fileName value.

If data.fileName is an empty string (or another falsy-but-valid value), this will incorrectly fall back to (data as any).filename. Prefer checking only for undefined, e.g. fileName: data.fileName ?? (data as any).filename, so intentional empty values are preserved.

Suggested change
public async mediaMessage(data: SendMediaDto, file?: any, isIntegration = false) {
const mediaData: SendMediaDto = { ...data };
const mediaData: SendMediaDto = {
...data,
// Normalize filename to fileName (handle case-insensitivity)
fileName: data.fileName || (data as any).filename,
};
public async mediaMessage(data: SendMediaDto, file?: any, isIntegration = false) {
const mediaData: SendMediaDto = {
...data,
// Normalize filename to fileName (handle case-insensitivity) while preserving intentional empty values
fileName: data.fileName ?? (data as any).filename,
};

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Inconsistência no nome da propriedade "fileName" no endpoint /message/sendMedia/{instance}

1 participant